// SPDX-License-Identifier: GPL-2.0-or-later

#include <Snake/App.hpp>

#include <Snake/Position.hpp>

#include <Snake/Snake.hpp>
#include <Snake/Field/RectShapeField.hpp>
#include <Snake/Field/Tile.hpp>

#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/System/Clock.hpp>

//TODO: replace with concrete headers
#include <SFML/Graphics.hpp>

App::App() :
	window(new sf::RenderWindow(sf::VideoMode::getDesktopMode(), "Snake", sf::Style::Fullscreen))
{
	this->window->setFramerateLimit(30);

	sf::Vector2u windowSize = this->window->getSize();

	this->game = new Game(50);

	//Field initialization
	sf::FloatRect rect;

	rect.width = windowSize.y / 12 * 11;
	rect.height = windowSize.y / 12 * 11;

	rect.top = (windowSize.y / 2) - (rect.height / 2);
	rect.left = (windowSize.x / 2) - (rect.width / 2);

	this->field = new RectShapeField(this->game->size, rect);
}

void App::run()
{
	// To minimize gap between creation and run()
	// Is it important?
	this->clock.restart();

	while(!this->quit)
	{
		this->update(this->clock.restart());
		this->draw();
	}
}

void App::update(sf::Time delta)
{
	// ...
	this->game->doStep();
	this->processEvents(delta);
	// ...
}

void App::processEvents(sf::Time delta)
{
	sf::Event event;
	while (this->window->pollEvent(event))
	{
		if(event.type == sf::Event::Closed)
			{
				this->quit = true;
			}
			else if(event.type == sf::Event::KeyPressed)
			{
				if(event.key.code == sf::Keyboard::Escape)
				{
					this->quit = true;
				}
			}
	}

	//Player movement
	if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
	{
		this->game->snake.direction = Direction::Left;
	}
	if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
	{
		this->game->snake.direction = Direction::Right;
	}
	if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
	{
		this->game->snake.direction = Direction::Top;
	}
	if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
	{
		this->game->snake.direction = Direction::Down;
	}
}

void App::draw()
{
	this->window->clear(sf::Color::White);
	this->field->erase();
	this->drawSnake();
	this->field->setTile(this->game->apple, {Tile::Type::Apple, Tile::Rotation::R0});
	this->window->draw(*this->field);
	this->window->display();
}

void App::drawSnake()
{
	for(auto segment : this->game->snake.body)
	{
		this->field->setTile(segment, {Tile::Type::SBody, Tile::Rotation::R0});
	}
	this->field->setTile(this->game->snake.body.front(), {Tile::Type::SHead, Tile::Rotation::R0});
}
